/**
  ******************************************************************************
  * @file    bs32f1xx_ll_i2c.c
  * @author  MCU Application Team
  * @brief   I2C LL module driver.
  ******************************************************************************
*/
#if defined(USE_FULL_LL_DRIVER)

/* Includes ------------------------------------------------------------------*/
#include "bs32f1xx_ll_i2c.h"
#include "bs32f1xx_ll_bus.h"

#ifdef  USE_FULL_ASSERT
#include "bs32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif

/** @addtogroup BS32F1xx_LL_Driver
  * @{
  */

#if defined (I2C1) || defined (I2C2)
/** @addtogroup I2C_LL I2C
  * @{
  */


/* Private macros ------------------------------------------------------------*/
/** @addtogroup I2C_LL_Private_Macros I2C Private Macros
  * @{
  */

#define IS_LL_I2C_ANALOG_FILTER(__VALUE__)      (((__VALUE__) == LL_I2C1_ANALOGFILTER_ENABLE) || \
                                                 ((__VALUE__) == LL_I2C1_ANALOGFILTER_DISABLE)|| \
                                                 ((__VALUE__) == LL_I2C2_ANALOGFILTER_ENABLE) || \
                                                 ((__VALUE__) == LL_I2C2_ANALOGFILTER_DISABLE))

#define IS_LL_I2C_DIGITAL_FILTER(__VALUE__)     (((__VALUE__) == LL_I2C1_DIGITALFILTER_ENABLE) || \
                                                 ((__VALUE__) == LL_I2C1_DIGITALFILTER_DISABLE)|| \
                                                 ((__VALUE__) == LL_I2C2_DIGITALFILTER_ENABLE) || \
                                                 ((__VALUE__) == LL_I2C2_DIGITALFILTER_DISABLE))

#define IS_LL_I2C_OWN_ADDRESS1(__VALUE__)       ((__VALUE__) <= 0x000000FFU)

#define IS_LL_I2C_TYPE_ACKNOWLEDGE(__VALUE__)   (((__VALUE__) == LL_I2C_ACK) || \
                                                 ((__VALUE__) == LL_I2C_NACK))

/**
  * @}
  */
  
/* Exported functions --------------------------------------------------------*/
/** @addtogroup I2C_LL_Exported_Functions
  * @{
  */

/**
  * @brief  De-initialize the I2C registers to their default reset values.
  * @param  I2Cx I2C Instance.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: I2C registers are de-initialized
  *          - ERROR: I2C registers are not de-initialized
  */
ErrorStatus LL_I2C_DeInit(I2C_TypeDef *I2Cx)
{
  ErrorStatus status = SUCCESS;

  /* Check the I2C Instance I2Cx */
  assert_param(IS_I2C_ALL_INSTANCE(I2Cx));

  if (I2Cx == I2C1)
  {
    /* Force reset of I2C clock */
    LL_APB1_ForceReset(LL_APB1_PERIPH_I2C1);

    /* Release reset of I2C clock */
    LL_APB1_ReleaseReset(LL_APB1_PERIPH_I2C1);
  }
  else if (I2Cx == I2C2)
  {
    /* Force reset of I2C clock */
    LL_APB1_ForceReset(LL_APB1_PERIPH_I2C2);

    /* Release reset of I2C clock */
    LL_APB1_ReleaseReset(LL_APB1_PERIPH_I2C2);

  }
  else
  {
    status = ERROR;
  }

  return status;
}

/**
  * @brief  Initialize the I2C registers according to the specified parameters in I2C_InitStruct.
  * @param  I2Cx I2C Instance.
  * @param  I2C_InitStruct pointer to a @ref LL_I2C_InitTypeDef structure.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: I2C registers are initialized
  *          - ERROR: Not applicable
  */
ErrorStatus LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct)
{
  /* Check the I2C Instance I2Cx */
  assert_param(IS_I2C_ALL_INSTANCE(I2Cx));

  /* Check the I2C parameters from I2C_InitStruct */
  assert_param(IS_LL_I2C_ANALOG_FILTER(I2C_InitStruct->AnalogFilter));
  assert_param(IS_LL_I2C_DIGITAL_FILTER(I2C_InitStruct->DigitalFilter));
  assert_param(IS_LL_I2C_OWN_ADDRESS1(I2C_InitStruct->OwnAddress1));
  assert_param(IS_LL_I2C_TYPE_ACKNOWLEDGE(I2C_InitStruct->TypeAcknowledge));

  /* Disable the selected I2Cx Peripheral */
  LL_I2C_Disable(I2Cx);

  /*---------------------------- I2Cx CR1 Configuration ------------------------
   * Configure the analog and digital noise filters with parameters :
   */
  
	if(I2C1 == I2Cx)
		MODIFY_REG(RCC->FILCR, RCC_FILCR_I2C1AFILE | RCC_FILCR_I2C1AFILE, I2C_InitStruct->AnalogFilter | I2C_InitStruct->DigitalFilter);
	else
		MODIFY_REG(RCC->FILCR, RCC_FILCR_I2C2AFILE | RCC_FILCR_I2C2AFILE, I2C_InitStruct->AnalogFilter | I2C_InitStruct->DigitalFilter);

  /*---------------------------- I2Cx TIMINGR Configuration --------------------
   * Configure the SDA setup, hold time and the SCL high, low period with parameter :
   * - Timing: I2C_TIMINGR_PRESC[3:0], I2C_TIMINGR_SCLDEL[3:0], I2C_TIMINGR_SDADEL[3:0],
   *           I2C_TIMINGR_SCLH[7:0] and I2C_TIMINGR_SCLL[7:0] bits
   */
  LL_I2C_SetTiming(I2Cx, I2C_InitStruct->Timing);

  /* Enable the selected I2Cx Peripheral */
  LL_I2C_Enable(I2Cx);

  /*---------------------------- I2Cx OAR1 Configuration -----------------------
   * Disable, Configure and Enable I2Cx device own address 1 with parameters :
   * - OwnAddress1:  I2C_OAR1_OA1[7:0] bits
   * - OwnAddrSize:  I2C_OAR1_OA1MODE bit
   */
  LL_I2C_DisableOwnAddress1(I2Cx);
  LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1);

  /* OwnAdress1 == 0 is reserved for General Call address */
  if (I2C_InitStruct->OwnAddress1 != 0U)
  {
    LL_I2C_EnableOwnAddress1(I2Cx);
  }

  /*---------------------------- I2Cx CR2 Configuration ------------------------
   * Configure the ACKnowledge or Non ACKnowledge condition
   * after the address receive match code or next received byte with parameter :
   * - TypeAcknowledge: I2C_CR2_NACK bit
   */
  LL_I2C_AcknowledgeNextData(I2Cx, I2C_InitStruct->TypeAcknowledge);
  
	
  return SUCCESS;
}

/**
  * @brief  Set each @ref LL_I2C_InitTypeDef field to default value.
  * @param  I2C_InitStruct Pointer to a @ref LL_I2C_InitTypeDef structure.
  * @retval None
  */
void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct)
{
  /* Set I2C_InitStruct fields to default values */
  I2C_InitStruct->Timing          = 0U;
  I2C_InitStruct->AnalogFilter    = 0U;
  I2C_InitStruct->DigitalFilter   = 0U;
  I2C_InitStruct->OwnAddress1     = 0U;
  I2C_InitStruct->TypeAcknowledge = LL_I2C_NACK;
}

/**
  * @brief  Enable Digital Noise Filter.
  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
  * @param  I2Cx I2C Instance.
  * @retval None
  */
void LL_I2C_EnableDigitalFilter(I2C_TypeDef *I2Cx)
{
	if(I2C1 == I2Cx)
    SET_BIT(RCC->FILCR, RCC_FILCR_I2C1DFILE);
	else
		SET_BIT(RCC->FILCR, RCC_FILCR_I2C2DFILE);
}

/**
  * @brief  Disable Digital Noise Filter.
  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
  * @param  I2Cx I2C Instance.
  * @retval None
  */
void LL_I2C_DisableDigitalFilter(I2C_TypeDef *I2Cx)
{
  if(I2C1 == I2Cx)
    CLEAR_BIT(RCC->FILCR, RCC_FILCR_I2C1DFILE);
	else
		CLEAR_BIT(RCC->FILCR, RCC_FILCR_I2C2DFILE);
}


/**
  * @brief  Check if Digital Noise Filter is enabled or disabled.
  * @param  I2Cx I2C Instance.
  * @retval State of bit (1 or 0).
  */
uint32_t LL_I2C_IsEnabledDigitalFilter(I2C_TypeDef *I2Cx)
{
	if(I2C1 == I2Cx)
		return ((READ_BIT(RCC->FILCR, RCC_FILCR_I2C1DFILE) != (RCC_FILCR_I2C1DFILE)) ? 1UL : 0UL);
	else
		return ((READ_BIT(RCC->FILCR, RCC_FILCR_I2C2DFILE) != (RCC_FILCR_I2C2DFILE)) ? 1UL : 0UL);
}

/**
  * @brief  Enable Analog Noise Filter.
  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
  * @param  I2Cx I2C Instance.
  * @retval None
  */
void LL_I2C_EnableAnalogFilter(I2C_TypeDef *I2Cx)
{
  if(I2C1 == I2Cx)
    SET_BIT(RCC->FILCR, RCC_FILCR_I2C1AFILE);
	else
		SET_BIT(RCC->FILCR, RCC_FILCR_I2C2AFILE);
}

/**
  * @brief  Disable Analog Noise Filter.
  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
  * @param  I2Cx I2C Instance.
  * @retval None
  */
void LL_I2C_DisableAnalogFilter(I2C_TypeDef *I2Cx)
{
  if(I2C1 == I2Cx)
    CLEAR_BIT(RCC->FILCR, RCC_FILCR_I2C1AFILE);
	else
		CLEAR_BIT(RCC->FILCR, RCC_FILCR_I2C2AFILE);
}

/**
  * @brief  Check if Analog Noise Filter is enabled or disabled.
  * @param  I2Cx I2C Instance.
  * @retval State of bit (1 or 0).
  */
uint32_t LL_I2C_IsEnabledAnalogFilter(I2C_TypeDef *I2Cx)
{
	if(I2C1 == I2Cx)
		return ((READ_BIT(RCC->FILCR, RCC_FILCR_I2C1AFILE) != (RCC_FILCR_I2C1AFILE)) ? 1UL : 0UL);
	else
		return ((READ_BIT(RCC->FILCR, RCC_FILCR_I2C2AFILE) != (RCC_FILCR_I2C2AFILE)) ? 1UL : 0UL);
}

/**
  * @}
  */
  
/**
  * @}
  */

#endif /* I2C1 || I2C2 */

/**
  * @}
  */

#endif /* USE_FULL_LL_DRIVER */

/************************ (C) COPYRIGHT BSMicroelectronics *****END OF FILE****/
